﻿// Type: System.ServiceModel.DomainServices.Client.EntitySet`1
// Assembly: System.ServiceModel.DomainServices.Client, Version=2.0.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
// Assembly location: C:\Program Files (x86)\Microsoft SDKs\RIA Services\v1.0\Libraries\Silverlight\System.ServiceModel.DomainServices.Client.dll

using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Threading;
using System.Windows.Data;

namespace System.ServiceModel.DomainServices.Client
{
  public sealed class EntitySet<TEntity> : EntitySet, IEnumerable<TEntity>, IEnumerable, ICollectionViewFactory where TEntity : Entity
  {
    private EventHandler<EntityCollectionChangedEventArgs<TEntity>> EntityAdded;
    private EventHandler<EntityCollectionChangedEventArgs<TEntity>> EntityRemoved;

    public event EventHandler<EntityCollectionChangedEventArgs<TEntity>> EntityAdded
    {
      add
      {
        EventHandler<EntityCollectionChangedEventArgs<TEntity>> eventHandler = this.EntityAdded;
        EventHandler<EntityCollectionChangedEventArgs<TEntity>> comparand;
        do
        {
          comparand = eventHandler;
          eventHandler = Interlocked.CompareExchange<EventHandler<EntityCollectionChangedEventArgs<TEntity>>>(ref this.EntityAdded, comparand + value, comparand);
        }
        while (eventHandler != comparand);
      }
      remove
      {
        EventHandler<EntityCollectionChangedEventArgs<TEntity>> eventHandler = this.EntityAdded;
        EventHandler<EntityCollectionChangedEventArgs<TEntity>> comparand;
        do
        {
          comparand = eventHandler;
          eventHandler = Interlocked.CompareExchange<EventHandler<EntityCollectionChangedEventArgs<TEntity>>>(ref this.EntityAdded, comparand - value, comparand);
        }
        while (eventHandler != comparand);
      }
    }

    public event EventHandler<EntityCollectionChangedEventArgs<TEntity>> EntityRemoved
    {
      add
      {
        EventHandler<EntityCollectionChangedEventArgs<TEntity>> eventHandler = this.EntityRemoved;
        EventHandler<EntityCollectionChangedEventArgs<TEntity>> comparand;
        do
        {
          comparand = eventHandler;
          eventHandler = Interlocked.CompareExchange<EventHandler<EntityCollectionChangedEventArgs<TEntity>>>(ref this.EntityRemoved, comparand + value, comparand);
        }
        while (eventHandler != comparand);
      }
      remove
      {
        EventHandler<EntityCollectionChangedEventArgs<TEntity>> eventHandler = this.EntityRemoved;
        EventHandler<EntityCollectionChangedEventArgs<TEntity>> comparand;
        do
        {
          comparand = eventHandler;
          eventHandler = Interlocked.CompareExchange<EventHandler<EntityCollectionChangedEventArgs<TEntity>>>(ref this.EntityRemoved, comparand - value, comparand);
        }
        while (eventHandler != comparand);
      }
    }

    public EntitySet()
      : base(typeof (TEntity))
    {
    }

    protected override IList CreateList()
    {
      return (IList) new List<TEntity>();
    }

    protected override Entity CreateEntity()
    {
      if (!typeof (TEntity).IsAbstract)
        return (Entity) Activator.CreateInstance(typeof (TEntity));
      throw new InvalidOperationException(string.Format((IFormatProvider) CultureInfo.CurrentCulture, Resources.Cannot_Create_Abstract_Entity, new object[1]
      {
        (object) typeof (TEntity)
      }));
    }

    public IEnumerator<TEntity> GetEnumerator()
    {
      return ((IEnumerable<TEntity>) this.List).GetEnumerator();
    }

    public void Attach(TEntity entity)
    {
      base.Attach((Entity) entity);
    }

    public void Detach(TEntity entity)
    {
      base.Detach((Entity) entity);
    }

    public void Add(TEntity entity)
    {
      base.Add((Entity) entity);
    }

    public void Remove(TEntity entity)
    {
      base.Remove((Entity) entity);
    }

    protected override void OnCollectionChanged(NotifyCollectionChangedAction action, object affectedObject, int index)
    {
      if (action == NotifyCollectionChangedAction.Add && this.EntityAdded != null)
        this.EntityAdded((object) this, new EntityCollectionChangedEventArgs<TEntity>((TEntity) affectedObject));
      else if (action == NotifyCollectionChangedAction.Remove && this.EntityRemoved != null)
        this.EntityRemoved((object) this, new EntityCollectionChangedEventArgs<TEntity>((TEntity) affectedObject));
      else if (action == NotifyCollectionChangedAction.Reset && this.EntityRemoved != null)
      {
        foreach (TEntity entity in Enumerable.Cast<TEntity>((IEnumerable) affectedObject))
          this.EntityRemoved((object) this, new EntityCollectionChangedEventArgs<TEntity>(entity));
      }
      base.OnCollectionChanged(action, affectedObject, index);
    }

    IEnumerator<TEntity> IEnumerable<TEntity>.GetEnumerator()
    {
      return this.GetEnumerator();
    }

    ICollectionView ICollectionViewFactory.CreateView()
    {
      return new CollectionViewSource()
      {
        Source = ((object) new EntitySet<TEntity>.ListCollectionViewProxy<TEntity>(this))
      }.View;
    }

    private class ListCollectionViewProxy<T> : IList, ICollection, IEnumerable<T>, IEnumerable, INotifyCollectionChanged, ICollectionChangedListener where T : Entity
    {
      private readonly object _syncRoot = new object();
      private readonly EntitySet<T> _source;
      private readonly WeakCollectionChangedListener _weakCollectionChangedLister;
      private NotifyCollectionChangedEventHandler CollectionChanged;

      public bool IsFixedSize
      {
        get
        {
          if (!this.Source.CanAdd)
            return !this.Source.CanRemove;
          else
            return false;
        }
      }

      public bool IsReadOnly
      {
        get
        {
          if (!this.Source.CanAdd)
            return !this.Source.CanRemove;
          else
            return false;
        }
      }

      public object this[int index]
      {
        get
        {
          if (index < 0 || index >= this.Source.Count)
            throw new ArgumentOutOfRangeException("index");
          else
            return this.Source.List[index];
        }
        set
        {
          throw new NotSupportedException(string.Format((IFormatProvider) CultureInfo.CurrentCulture, Resource.IsNotSupported, new object[1]
          {
            (object) "Indexed setting"
          }));
        }
      }

      public int Count
      {
        get
        {
          return this.Source.Count;
        }
      }

      public bool IsSynchronized
      {
        get
        {
          return false;
        }
      }

      public object SyncRoot
      {
        get
        {
          return this._syncRoot;
        }
      }

      EntitySet<T> Source
      {
        private get
        {
          return this._source;
        }
      }

      public event NotifyCollectionChangedEventHandler CollectionChanged
      {
        add
        {
          NotifyCollectionChangedEventHandler changedEventHandler = this.CollectionChanged;
          NotifyCollectionChangedEventHandler comparand;
          do
          {
            comparand = changedEventHandler;
            changedEventHandler = Interlocked.CompareExchange<NotifyCollectionChangedEventHandler>(ref this.CollectionChanged, comparand + value, comparand);
          }
          while (changedEventHandler != comparand);
        }
        remove
        {
          NotifyCollectionChangedEventHandler changedEventHandler = this.CollectionChanged;
          NotifyCollectionChangedEventHandler comparand;
          do
          {
            comparand = changedEventHandler;
            changedEventHandler = Interlocked.CompareExchange<NotifyCollectionChangedEventHandler>(ref this.CollectionChanged, comparand - value, comparand);
          }
          while (changedEventHandler != comparand);
        }
      }

      internal ListCollectionViewProxy(EntitySet<T> source)
      {
        this._source = source;
        this._weakCollectionChangedLister = WeakCollectionChangedListener.CreateIfNecessary((object) this._source, (ICollectionChangedListener) this);
      }

      public int Add(object value)
      {
        T entity = value as T;
        if ((object) entity == null)
        {
          throw new ArgumentException(string.Format((IFormatProvider) CultureInfo.CurrentCulture, Resource.MustBeAnEntity, new object[1]
          {
            (object) "value"
          }), "value");
        }
        else
        {
          this.Source.Add(entity);
          return this.IndexOf((object) entity);
        }
      }

      public void Clear()
      {
        this.Source.Clear();
      }

      public bool Contains(object value)
      {
        return this.IndexOf(value) >= 0;
      }

      public int IndexOf(object value)
      {
        return this.Source.List.IndexOf(value);
      }

      public void Insert(int index, object value)
      {
        throw new NotSupportedException(string.Format((IFormatProvider) CultureInfo.CurrentCulture, Resource.IsNotSupported, new object[1]
        {
          (object) "Insert"
        }));
      }

      public void Remove(object value)
      {
        T entity = (T) value;
        if ((object) entity == null)
          return;
        this.Source.Remove(entity);
      }

      public void RemoveAt(int index)
      {
        this.Remove(this[index]);
      }

      public void CopyTo(Array array, int index)
      {
        this.Source.List.CopyTo(array, index);
      }

      public IEnumerator<T> GetEnumerator()
      {
        return this.Source.GetEnumerator();
      }

      IEnumerator IEnumerable.GetEnumerator()
      {
        return (IEnumerator) this.GetEnumerator();
      }

      private void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
      {
        NotifyCollectionChangedEventHandler changedEventHandler = this.CollectionChanged;
        if (changedEventHandler == null)
          return;
        changedEventHandler((object) this, e);
      }

      private void OnSourceCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
      {
        this.OnCollectionChanged(e);
      }

      void ICollectionChangedListener.OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
      {
        this.OnSourceCollectionChanged(sender, e);
      }
    }
  }
}
